package com.miao.util;

import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.UUID;

/**
 * AES: Advanced Encryption Standard 高级加密标准
 * 最常见的对称加密算法，即加密和解密使用同样的密钥，加密结果可逆
 * 特点：加密速度非常快，适合经常发送数据的场合
 *
 */
public class AESUtil {
    public static final String DEFAULT_SEED = "fjaweofjoawejfawoefj";

    private static final String KEY_ALGORITHM = "AES";

    private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

    private final Cipher decryptCipher;

    private final Cipher encryptCipher;

    private final String seed;

    public AESUtil(String seed) throws Exception {
        this.seed = seed;
        decryptCipher = Cipher.getInstance(KEY_ALGORITHM);
        encryptCipher = Cipher.getInstance(KEY_ALGORITHM);
        decryptCipher.init(Cipher.DECRYPT_MODE, this.getSecretKey());
        encryptCipher.init(Cipher.ENCRYPT_MODE, this.getSecretKey());
    }

    /**
     * 使用Base64解码和加密密钥解密内容
     *
     * @param content 要解密的经过Base64编码的内容
     * @return 解密后的字符串
     * @throws Exception 如果解密过程中发生错误，则抛出异常
     */
    public String decrypt(String content) throws Exception {
        // 使用Base64解码器将输入内容解码为字节数组
        byte[] bytes = Base64.getDecoder().decode(content);

        // 使用Cipher对象解密字节数组
        byte[] result = decryptCipher.doFinal(bytes);

        // 将解密后的字节数组转换为字符串并返回
        return new String(result, StandardCharsets.UTF_8);
    }

    /**
     * 对给定内容进行加密并返回加密后的字符串
     * 该方法使用之前初始化的加密器encryptCipher对内容进行加密
     * 加密后的字节数组被转换为Base64编码的字符串，以便于传输或存储
     *
     * @param content 需要加密的内容
     * @return 加密后并经过Base64编码的内容
     * @throws Exception 如果加密过程中发生错误
     */
    public String encrypt(String content) throws Exception {
        // 使用encryptCipher对内容进行加密，content.getBytes(StandardCharsets.UTF_8)将字符串转换为字节数组
        byte[] result = encryptCipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
        // 将加密后的字节数组转换为Base64编码的字符串
        return Base64.getEncoder().encodeToString(result);
    }

    /**
     * 生成一个秘密密钥
     * 该方法使用指定的算法生成一个对称加密用的秘密密钥
     * 主要步骤包括：
     * 1. 使用SHA1PRNG算法创建一个安全随机数生成器，并用预设的种子对其进行初始化
     * 2. 获取指定算法（KEY_ALGORITHM）的密钥生成器实例，并用之前的安全随机数生成器初始化
     * 3. 调用密钥生成器的generateKey方法生成并返回秘密密钥
     *
     * @return SecretKey 实例，用于对称加密
     * @throws Exception 如果安全随机数生成器或密钥生成器的初始化出现问题
     */
    public SecretKey getSecretKey() throws Exception {
        // 创建一个安全随机数生成器实例
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        // 使用种子初始化安全随机数生成器
        random.setSeed(seed.getBytes());
        // 获取指定算法的密钥生成器实例
        KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
        // 使用安全随机数生成器初始化密钥生成器，指定密钥长度为128位
        kg.init(128, random);
        // 生成并返回秘密密钥
        return kg.generateKey();
    }

    //ef2e3fdb-e32d-4e0d-a4b8-91f2688e7ab5
    public static void main(String[] args) throws Exception {
        String password = "123456";
//        String seed = AESUtil.DEFAULT_SEED;
        String seed = UUID.randomUUID().toString();     //随机生成不重复的32的种子
        System.out.println("seed:" + seed);

        AESUtil aesUtil = new AESUtil(seed);
        String encodePassword = aesUtil.encrypt(password);
        System.out.println("加密后的密码：" + encodePassword);

        String decodePassword = aesUtil.decrypt(encodePassword);
        System.out.println("解密后的密码：" + decodePassword);
    }
}
